#pragma once

#include "ElementImport.h"

#include "Namespace.h"
#include "PackageableElement.h"

namespace uml {

const QString ElementImport::alias_default_ = "";
void ElementImport::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    DirectedRelationship::fromJson(json, errorList);
    alias_ = json.value("alias").toString(alias_default_);
    importedElement_ = JsonSerializable::create<PackageableElement>(json.value("importedElement"), errorList);

    importingNamespace_ = JsonSerializable::create<Namespace>(json.value("importingNamespace"), errorList);

    visibility_ = (VisibilityKind)json.value("visibility").toInt((int)visibility_);
}

void ElementImport::toJson(QJsonObject& json) {
    DirectedRelationship::toJson(json);
    if (alias_ != alias_default_) {
        json.insert("alias", alias_);
    }
    if (importedElement_) {
        QJsonObject importedElement_json;
        importedElement_->toJson(importedElement_json);
        json.insert("importedElement", importedElement_json);
    }
    if (importingNamespace_) {
        QJsonObject importingNamespace_json;
        importingNamespace_->toJson(importingNamespace_json);
        json.insert("importingNamespace", importingNamespace_json);
    }
    json.insert("visibility", (int)visibility_);
}

/// <summary>
/// getName
    /// The query getName() returns the name under which the imported PackageableElement
    /// will be known in the importing namespace.
/// </summary>
    /// <code>
    /// result = (if alias->notEmpty() then
    ///   alias
    /// else
    ///   importedElement.name
    /// endif)
    /// </code>
QString ElementImport::getName() const
{
    return "";
}

/// <summary>
/// alias getter
/// Specifies the name that should be added to the importing Namespace in lieu of
/// the name of the imported PackagableElement. The alias must not clash with any
/// other member in the importing Namespace. By default, no alias is used.
/// </summary>
QString ElementImport::alias() const {
    return alias_;
}

/// <summary>
/// alias setter
/// Specifies the name that should be added to the importing Namespace in lieu of
/// the name of the imported PackagableElement. The alias must not clash with any
/// other member in the importing Namespace. By default, no alias is used.
/// </summary>
void ElementImport::setAlias(const QString& value) {
    alias_ = value;
}

/// <summary>
/// importedElement getter
/// Specifies the PackageableElement whose name is to be added to a Namespace.
/// </summary>
shared_ptr<PackageableElement> ElementImport::importedElement() const {
    return importedElement_;
}

/// <summary>
/// importedElement setter
/// Specifies the PackageableElement whose name is to be added to a Namespace.
/// </summary>
void ElementImport::setImportedElement(shared_ptr<PackageableElement> value) {
    importedElement_ = value;
}

/// <summary>
/// importingNamespace getter
/// Specifies the Namespace that imports a PackageableElement from another
/// Namespace.
/// </summary>
shared_ptr<Namespace> ElementImport::importingNamespace() const {
    return importingNamespace_;
}

/// <summary>
/// importingNamespace setter
/// Specifies the Namespace that imports a PackageableElement from another
/// Namespace.
/// </summary>
void ElementImport::setImportingNamespace(shared_ptr<Namespace> value) {
    importingNamespace_ = value;
}

/// <summary>
/// visibility getter
/// Specifies the visibility of the imported PackageableElement within the
/// importingNamespace, i.e., whether the  importedElement will in turn be visible
/// to other Namespaces. If the ElementImport is public, the importedElement will be
/// visible outside the importingNamespace while, if the ElementImport is private,
/// it will not.
/// </summary>
VisibilityKind ElementImport::visibility() const {
    return visibility_;
}

/// <summary>
/// visibility setter
/// Specifies the visibility of the imported PackageableElement within the
/// importingNamespace, i.e., whether the  importedElement will in turn be visible
/// to other Namespaces. If the ElementImport is public, the importedElement will be
/// visible outside the importingNamespace while, if the ElementImport is private,
/// it will not.
/// </summary>
void ElementImport::setVisibility(VisibilityKind value) {
    visibility_ = value;
}

} // namespace uml
